﻿using Coldairarrow.Entity.A;
using Coldairarrow.Util;
using EFCore.Sharding;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Coldairarrow.Business
{
    /// <summary>
    /// 描述：业务处理基类
    /// </summary>
    /// <typeparam name="T">泛型约束（数据库实体）</typeparam>
    public abstract partial class BaseBusiness<T> where T : class, new()
    {
        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="db">注入数据库</param>
        public BaseBusiness(IDbAccessor db)
        {
            Db = db;
        }

        #endregion

        #region 私有成员

        protected virtual string _valueField { get; } = "Id";
        protected virtual string _textField { get => throw new Exception("请在子类重写"); }

        #endregion

        #region 外部属性

        /// <summary>
        /// 业务仓储接口(支持软删除),支持联表操作
        /// 注：若需要访问逻辑删除的数据,请使用IDbAccessor.FullRepository
        /// 注：仅支持单线程操作
        /// </summary>
        public IDbAccessor Db { get; }

        #endregion

        #region 事物提交

        public (bool Success, Exception ex) RunTransaction(Action action, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
        {
            return Db.RunTransaction(action, isolationLevel);
        }
        public async Task<(bool Success, Exception ex)> RunTransactionAsync(Func<Task> action, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
        {
            return await Db.RunTransactionAsync(action, isolationLevel);
        }

        #endregion

        #region 增加数据

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public int Insert(T entity)
        {
            return Db.Insert(entity);
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public async Task<int> InsertAsync(T entity)
        {
            return await Db.InsertAsync(entity);
        }

        /// <summary>
        /// 添加多条数据
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        public int Insert(List<T> entities)
        {
            return Db.Insert(entities);
        }

        /// <summary>
        /// 添加多条数据
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        public async Task<int> InsertAsync(List<T> entities)
        {
            return await Db.InsertAsync(entities);
        }

        /// <summary>
        /// 批量添加数据,速度快
        /// </summary>
        /// <param name="entities"></param>
        public void BulkInsert(List<T> entities)
        {
            Db.BulkInsert(entities);
        }

        #endregion

        #region 删除数据

        /// <summary>
        /// 删除所有数据
        /// </summary>
        public int DeleteAll()
        {
            return Db.DeleteAll<T>();
        }

        /// <summary>
        /// 删除所有数据
        /// </summary>
        public async Task<int> DeleteAllAsync()
        {
            return await Db.DeleteAllAsync<T>();
        }

        /// <summary>
        /// 删除指定主键数据
        /// </summary>
        /// <param name="key"></param>
        public int Delete(string key)
        {
            return Db.Delete<T>(key);
        }

        /// <summary>
        /// 删除指定主键数据
        /// </summary>
        /// <param name="key"></param>
        public async Task<int> DeleteAsync(string key)
        {
            return await Db.DeleteAsync<T>(key);
        }

        /// <summary>
        /// 通过主键删除多条数据
        /// </summary>
        /// <param name="keys"></param>
        public int Delete(List<string> keys)
        {
            return Db.Delete<T>(keys);
        }

        /// <summary>
        /// 通过主键删除多条数据
        /// </summary>
        /// <param name="keys"></param>
        public async Task<int> DeleteAsync(List<string> keys)
        {
            return await Db.DeleteAsync<T>(keys);
        }

        /// <summary>
        /// 通过其他列删除多条数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<int> DeleteOtherIdAsync(object where)
        {
            return await Db.DeleteSqlAsync<T>((Expression<Func<T, bool>>)where);
        }

        /// <summary>
        /// 删除单条数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public int Delete(T entity)
        {
            return Db.Delete<T>(entity);
        }

        /// <summary>
        /// 删除单条数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public async Task<int> DeleteAsync(T entity)
        {
            return await Db.DeleteAsync(entity);
        }

        /// <summary>
        /// 删除多条数据
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        public int Delete(List<T> entities)
        {
            return Db.Delete<T>(entities);
        }

        /// <summary>
        /// 删除多条数据
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        public async Task<int> DeleteAsync(List<T> entities)
        {
            return await Db.DeleteAsync<T>(entities);
        }

        /// <summary>
        /// 删除指定条件数据
        /// </summary>
        /// <param name="condition">筛选条件</param>
        public int Delete(Expression<Func<T, bool>> condition)
        {
            return Db.Delete(condition);
        }

        /// <summary>
        /// 删除指定条件数据
        /// </summary>
        /// <param name="condition">筛选条件</param>
        public async Task<int> DeleteAsync(Expression<Func<T, bool>> condition)
        {
            return await Db.DeleteAsync(condition);
        }

        /// <summary>
        /// 使用SQL语句按照条件删除数据
        /// 用法:Delete_Sql"Base_User"(x=&gt;x.Id == "Admin")
        /// 注：生成的SQL类似于DELETE FROM [Base_User] WHERE [Name] = 'xxx' WHERE [Id] = 'Admin'
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns>
        /// 影响条数
        /// </returns>
        public int DeleteSql(Expression<Func<T, bool>> where)
        {
            return Db.DeleteSql(where);
        }

        /// <summary>
        /// 使用SQL语句按照条件删除数据
        /// 用法:Delete_Sql"Base_User"(x=&gt;x.Id == "Admin")
        /// 注：生成的SQL类似于DELETE FROM [Base_User] WHERE [Name] = 'xxx' WHERE [Id] = 'Admin'
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns>
        /// 影响条数
        /// </returns>
        public async Task<int> DeleteSqlAsync(Expression<Func<T, bool>> where)
        {
            return await Db.DeleteSqlAsync(where);
        }

        #endregion

        #region 更新数据

        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public int Update(T entity)
        {
            return Db.Update(entity);
        }

        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="entity">实体对象</param>
        public async Task<int> UpdateAsync(T entity)
        {
            return await Db.UpdateAsync(entity);
        }
        public async Task<int> UpdateAsync(T entity, List<string> props)
        {
            return await Db.UpdateAsync(entity, props);
        }

        /// <summary>
        /// 自建条件的修改多条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public async Task<int> ExecuteSqlAsync(string sql)
        {
            return await Db.ExecuteSqlAsync(sql);

        }

        /// <summary>
        /// 更新多条数据
        /// </summary>
        /// <param name="entities">数据列表</param>
        public int Update(List<T> entities)
        {
            return Db.Update(entities);
        }

        /// <summary>
        /// 更新多条数据
        /// </summary>
        /// <param name="entities">数据列表</param>
        public async Task<int> UpdateAsync(List<T> entities)
        {
            return await Db.UpdateAsync(entities);
        }

        /// <summary>
        /// 指定条件更新
        /// </summary>
        /// <param name="whereExpre">筛选表达式</param>
        /// <param name="set">更改属性回调</param>
        public int Update(Expression<Func<T, bool>> whereExpre, Action<T> set)
        {
            return Db.Update(whereExpre, set);
        }

        /// <summary>
        /// 指定条件更新
        /// </summary>
        /// <param name="whereExpre">筛选表达式</param>
        /// <param name="set">更改属性回调</param>
        public async Task<int> UpdateAsync(Expression<Func<T, bool>> whereExpre, Action<T> set)
        {
            return await Db.UpdateAsync(whereExpre, set);
        }

        /// <summary>
        /// 使用SQL语句按照条件更新
        /// 用法:UpdateWhere_Sql"Base_User"(x=>x.Id == "Admin",("Name","小明"))
        /// 注：生成的SQL类似于UPDATE [TABLE] SET [Name] = 'xxx' WHERE [Id] = 'Admin'
        /// </summary>
        /// <param name="where">筛选条件</param>
        /// <param name="values">字段值设置</param>
        /// <returns>影响条数</returns>
        public int UpdateSql(Expression<Func<T, bool>> where, params (string field, UpdateType updateType, object value)[] values)
        {
            return Db.UpdateSql(where, values);
        }

        /// <summary>
        /// 使用SQL语句按照条件更新
        /// 用法:UpdateWhere_Sql"Base_User"(x=>x.Id == "Admin",("Name","小明"))
        /// 注：生成的SQL类似于UPDATE [TABLE] SET [Name] = 'xxx' WHERE [Id] = 'Admin'
        /// </summary>
        /// <param name="where">筛选条件</param>
        /// <param name="values">字段值设置</param>
        /// <returns>影响条数</returns>
        public async Task<int> UpdateSqlAsync(Expression<Func<T, bool>> where, params (string field, UpdateType updateType, object value)[] values)
        {
            return await Db.UpdateSqlAsync(where, values);
        }

        #endregion

        #region 查询数据

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public T GetEntity(params object[] keyValue)
        {
            return Db.GetEntity<T>(keyValue);
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public async Task<T> GetEntityAsync(params object[] keyValue)
        {
            return await Db.GetEntityAsync<T>(keyValue);
        }

        /// <summary>
        /// 根据任意条件获取实体
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<T> GetEntityByWhereAsync(Expression<Func<T, bool>> where)
        {
            return await Db.GetIQueryable<T>().FirstOrDefaultAsync(where);
        }

        /// <summary>
        /// 获取表的所有数据，当数据量很大时不要使用！
        /// </summary>
        /// <returns></returns>
        public List<T> GetList()
        {
            return Db.GetIQueryable<T>().ToList();
        }

        /// <summary>
        /// 获取表的所有数据，当数据量很大时不要使用！
        /// </summary>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync()
        {
            return await Db.GetIQueryable<T>().ToListAsync();
        }

        /// <summary>
        /// 获取实体对应的表，延迟加载，主要用于支持Linq查询操作
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<T> GetIQueryable()
        {
            return Db.GetIQueryable<T>();
        }

        #endregion

        #region 执行Sql语句

        /// <summary>
        /// sql查询返回datatable
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public async Task<DataTable> GetDataTableWithSqlAsync(string sql)
        {
            return await Db.GetDataTableWithSqlAsync(sql);
        }
        /// <summary>
        /// sql查询返回T
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public async Task<List<T>> GetEntityWithSqlAsync(string sql)
        {
            return await Db.GetListBySqlAsync<T>(sql);
        }
        #endregion

        #region 业务返回

        /// <summary>
        /// 返回成功
        /// </summary>
        /// <returns></returns>
        public AjaxResult Success()
        {
            AjaxResult res = new AjaxResult
            {
                Success = true,
                Msg = "请求成功！",
            };

            return res;
        }

        /// <summary>
        /// 返回成功
        /// </summary>
        /// <param name="data">返回数据</param>
        /// <returns></returns>
        public AjaxResult<U> Success<U>(U data)
        {
            AjaxResult<U> res = new AjaxResult<U>
            {
                Success = true,
                Msg = "操作成功",
                Data = data
            };

            return res;
        }

        /// <summary>
        /// 返回成功
        /// </summary>
        /// <param name="data">返回数据</param>
        /// <param name="msg">返回消息</param>
        /// <returns></returns>
        public AjaxResult<U> Success<U>(U data, string msg)
        {
            AjaxResult<U> res = new AjaxResult<U>
            {
                Success = true,
                Msg = msg,
                Data = data
            };

            return res;
        }

        /// <summary>
        /// 返回错误
        /// </summary>
        /// <returns></returns>
        public AjaxResult Error()
        {
            AjaxResult res = new AjaxResult
            {
                Success = false,
                Msg = "请求失败！",
            };

            return res;
        }

        /// <summary>
        /// 返回错误
        /// </summary>
        /// <param name="msg">错误提示</param>
        /// <returns></returns>
        public AjaxResult Error(string msg)
        {
            AjaxResult res = new AjaxResult
            {
                Success = false,
                Msg = msg,
            };

            return res;
        }

        /// <summary>
        /// 构建前端Select远程搜索数据
        /// </summary>
        /// <param name="input">查询参数</param>
        /// <returns></returns>
        public async Task<List<SelectOption>> GetOptionListAsync(OptionListInputDTO input)
        {
            return await GetOptionListAsync(input, _textField, _valueField, null);
        }

        public IQueryable<T> GetQueryable<T>() where T : class, new()
        {
            return Db.GetIQueryable<T>();
        }
        /// <summary>
        /// 构建前端Select远程搜索数据
        /// </summary>
        /// <param name="input">查询参数</param>
        /// <param name="textFiled">文本字段</param>
        /// <param name="valueField">值字段</param>
        /// <param name="source">指定数据源</param>
        /// <returns></returns>
        public async Task<List<SelectOption>> GetOptionListAsync(OptionListInputDTO input, string textFiled, string valueField, IQueryable<T> source = null)
        {
            PageInput pageInput = new PageInput
            {
                PageRows = 10
            };

            List<T> selectedList = new List<T>();
            string where = " 1=1 ";
            List<string> ids = input.selectedValues;
            if (ids.Count > 0)
            {
                selectedList = await GetNewQ().Where($"@0.Contains({valueField})", ids).ToListAsync();

                where += $" && !@0.Contains({valueField})";
            }

            if (!input.q.IsNullOrEmpty())
            {
                where += $" && it.{textFiled}.Contains(@1)";
            }
            List<T> newQList = await GetNewQ().Where(where, ids, input.q).GetPageListAsync(pageInput);

            var resList = selectedList.Concat(newQList).Select(x => new SelectOption
            {
                value = x.GetPropertyValue(valueField)?.ToString(),
                text = x.GetPropertyValue(textFiled)?.ToString()
            }).ToList();

            return resList;

            IQueryable<T> GetNewQ()
            {
                return source ?? GetIQueryable();
            }
        }

        #endregion

        #region 其它操作
        /// <summary>
        /// 获取要更新的字段
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public List<string> GetFieldList(T entity)
        {
            List<string> props = new List<string>();
            foreach (System.Reflection.PropertyInfo p in entity.GetType().GetProperties())
            {
                if (!p.GetValue(entity, null).IsNullOrEmpty())
                {
                    if (!p.Name.Equals("Id"))
                    {
                        props.Add(p.Name);
                    }
                }
            }
            return props;
        }

        /// <summary>
        /// 获取要更新的字段
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public List<string> GetFieldList<T>(T entity)
        {
            List<string> props = new List<string>();
            foreach (System.Reflection.PropertyInfo p in entity.GetType().GetProperties())
            {
                if (!p.GetValue(entity, null).IsNullOrEmpty())
                {
                    if (!p.Name.Equals("Id"))
                    {
                        props.Add(p.Name);
                    }
                }
            }
            return props;
        }

        /// <summary>
        /// 获取查询条件实体集合
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public List<ConditionDTO> GetConditionList(object entity)
        {
            List<ConditionDTO> props = new List<ConditionDTO>();
            foreach (System.Reflection.PropertyInfo p in entity.GetType().GetProperties())
            {
                if (!p.GetValue(entity, null).IsNullOrEmpty())
                {
                    ConditionDTO prop = new ConditionDTO()
                    {
                        Condition = p.Name,
                        Keyword = p.GetValue(entity).ToString()
                    };
                    props.Add(prop);
                }
            }
            return props;
        }
        #endregion

        #region 二维码请求头
        /// <summary>
        /// 用户key值
        /// </summary>
        public string h_User = "01";
        /// <summary>
        /// 生产订单key值
        /// </summary>
        public string h_ProductionOrder = "02";
        /// <summary>
        /// 生产订单明细key值
        /// </summary>
        public string h_ProductionOrderDetail = "03";
        /// <summary>
        /// 物料key值
        /// </summary>
        public string h_Material = "04";
        /// <summary>
        /// 组织key值
        /// </summary>
        public string h_Department = "05";
        /// <summary>
        /// 货位key值
        /// </summary>
        public string h_Location = "06";
        /// <summary>
        /// 库区key值
        /// </summary>
        public string h_StorArea = "07";
        /// <summary>
        /// 工作站key值
        /// </summary>
        public string h_WorkStation = "08";
        /// <summary>
        /// 货架key值
        /// </summary>
        public string h_Rack = "09";
        /// <summary>
        /// 工位key值
        /// </summary>
        public string h_Station = "10";
        /// <summary>
        /// 设备Key值
        /// </summary>
        public string h_Device = "11";
        /// <summary>
        /// 清单Key值
        /// </summary>
        public string h_DetailedList = "12";
        /// <summary>
        /// 打包Key值
        /// </summary>
        public string h_Pack = "13";
        /// <summary>
        /// 成品Key值(PDA统计)
        /// </summary>
        public string h_FinishedProduct = "14";
        /// <summary>
        /// 车间Key值
        /// </summary>
        public string h_FWorkshop = "15";
        /// <summary>
        /// 派工单明细Key值
        /// </summary>
        public string h_DispatchDetail = "16";

        /// <summary>
        /// 派车单Key值
        /// </summary>
        public string h_Bill = "17";

        /// <summary>
        /// 通知入库Key值
        /// </summary>
        public string h_WarehousingNotice = "18";

        /// <summary>
        /// 入库单Key值
        /// </summary>
        public string h_Warehousing = "19";

        /// <summary>
        ///收货单Key值
        /// </summary>
        public string h_TdRe = "23";

        /// <summary>
        ///出库单Key值
        /// </summary>
        public string h_OutStorage = "24";

        /// <summary>
        ///调拨单Key值
        /// </summary>
        public string h_Allocate = "25";

     
        /// <summary>
        /// 回货主表Key
        /// </summary>
        public string ReturnOwner="26";
        /// <summary>
        /// 回货子表Key
        /// </summary>
        public string Returnee = "27";

        /// <summary>
        /// 盘点单Key
        /// </summary>
        public string h_cehck = "28";

        /// <summary>
        /// 外协单Key
        /// </summary>
        public string o_outsour = "29";
        /// <summary>
        /// 外协订单明细Key
        /// </summary>
        public string o_OutsourcingBillDetail = "30";

        /// <summary>
        /// 流转单Key值
        /// </summary>
        public string h_Circulation = "31";

        /// <summary>
        /// 托盘Key值
        /// </summary>
        public string TrayKey = "32";
        /// <summary>
        /// 派工主表Key
        /// </summary>
        public string h_Dispatch = "33";

        /// <summary>
        /// 采购单Key值
        /// </summary>
        public string h_Purchase = "34";

        /// <summary>
        /// 仓库签到Key值
        /// </summary>
        public string h_StorSignIn = "35";

        /// <summary>
        /// 看板Key值
        /// </summary>
        public string Registration = "36";
        /// 维修工单key值
        /// </summary>
        public string base_RepairOrderCode = "37";
        /// <summary>
        /// 维修工单明细Key值
        /// </summary>
        public string base_RepairOrderDetailsCode = "38";

        /// <summary>
        /// 发货通知单Key值
        /// </summary>
        public string PB_DeliveryNoticeCode = "39";

        /// <summary>
        /// 资产管理Key值
        /// </summary>
        public string h_Assets = "40";

        /// <summary>
        /// 资产管理盘点单Key值
        /// </summary>
        public string h_AssetsCheck = "41";

        #endregion

        #region MongoDB集合枚举
        public string PrintQueueCollection = "PrintQueue"; //打印队列集合

        public string ErrLogCollection = "ErrLog";  //错误日志

        public string JobBookingOperation = "PB_JobBookingDetailed";  //报工操作明细

        public string MessageNoticeTips = "MessageNoticeTips";  //消息推送集合
        public string StpeQueueCollection = "StpeQueue"; //备货打印集合
        #endregion

        #region
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public string GetTimeStamp()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        #endregion

        #region  加密Key值

        public string Key = "QspZCjj7iEGrPWQUg4eqyQ";

        #endregion
    }
}
